#pragma once

#include <iostream>
#include <string>
#include <memory>
#include <functional>
#include <unordered_map>

#include "TcpServer.hpp"
#include "HttpProtocol.hpp"

using namespace TcpServerModule;

using http_handler_t = std::function<void(HttpRequset &, HttpResponse &)>;

class HttpServer
{
public:
    HttpServer(int port)
        : _tsvr(std::make_unique<TcpServer>(port))
    {
    }

    ~HttpServer() {}

    void Register(std::string funcname, http_handler_t func)
    {
        _route[funcname] = func;
    }

    void Start()
    {
        _tsvr->InitServer([this](SockPtr sockfd, InetAddr client)
                          { return this->HanlerRequset(sockfd, client); });

        _tsvr->Loop();
    }

    bool SafeCheck(const std::string &service)
    {
        auto iter = _route.find(service);
        return iter != _route.end();
    }

    bool HanlerRequset(SockPtr sockfd, InetAddr client)
    {
        LOG(LogLevel::DEBUG) << "HttpServer: get a new client: " << sockfd->Fd() << " addr info: " << client.Addr();

        // 1. 读取浏览器发送的http请求
        std::string http_requset;
        sockfd->Recv(&http_requset);

        // 2. 请求反序列化
        HttpRequset req;
        req.Deserialize(http_requset);
        
        // 3. 根据请求构建响应
        HttpResponse resp;
        if (req.IsHasArgs()) // 动态交互请求(含有参数): 登入, 注册... 
        {
            // GET 请求的参数在 URL 中
            // POST请求的参数在 body中
            std::string service = req.Path();
            if(SafeCheck(service))
            {
                _route[service](req, resp); // login
            }
            else
            {
                resp.Build(req);
            }
        }
        else // 请求一般的静态资源(不含参数): 网页, 图片, 视频...
        {
            resp.Build(req);
        }

        // 4. 响应序列化
        std::string http_response;
        resp.Serialize(&http_response);

        // 5. 发送响应给用户
        sockfd->Send(http_response);

        return true;
    }

private:
    std::unique_ptr<TcpServer> _tsvr;
    std::unordered_map<std::string, http_handler_t> _route; // 功能路由
};